#include "stdafx.h"
#include "objectloader.h"

CObjectLoader::CObjectLoader(void)
{
}

CObjectLoader::~CObjectLoader(void)
{
	logi("CObjectLoader::~CObjectLoader");
}

std_method_impl CObjectLoader::Load(LPSTRING path, LPCSTR name)
{
	rc_assert(path, E_FAIL);
	HRESULT hr = S_OK;
	
	SYNC_OBJ(&m_lockSection)

	ContainerTableiterator it = m_mapContainer.find(name);
	rc_assert((m_mapContainer.end() == it), S_OK);

	ContainerBooliterator ib = m_mapContainer.insert(std::make_pair(name, CComLoader()));
	rc_assert(ib.second, E_FAIL);

	it = ib.first;

	hr = it->second.LoadCom(path);
	rc_assert(hr == S_OK, E_FAIL);

	LONG lCount = it->second.GetCount();

	LONG loop = 0;
	for (loop = 0; loop < lCount; loop++)
	{
		CLSID clsid = it->second.GetAt(loop);
		LPCSTR lpProgId = it->second.ProgIDFromCLSID(clsid);
		rc_assert_continue(lpProgId && *lpProgId)

		ClsIdTableiterator it = m_mapCls.find(clsid);
		rc_assert_continue((m_mapCls.end() == it));

		ClsIdTableBooliterator ib = m_mapCls.insert(std::make_pair(clsid, ClsInfo()));
		rc_assert_continue(ib.second);

		it = ib.first;
		it->second.pname = name;
		it->second.progid = lpProgId;
	}


	return  it->second.DllStartServer();
}

std_method_impl CObjectLoader::Free()
{
	SYNC_OBJ(&m_lockSection)

	ContainerTableiterator it = m_mapContainer.begin();
	while (it != m_mapContainer.end())
	{
		it->second.DllStopServer();
		it++;
	}

	m_mapContainer.clear();
	return S_OK;
}

std_method_type_impl(DWORD) CObjectLoader::GetCount()
{
	SYNC_OBJ(&m_lockSection)
	return m_mapContainer.size();
}

std_method_impl CObjectLoader::CreateInstance(IBase* rot, REFCLSID clsid, IBase* punk, REFIID iid, void **ppv)
{
	HRESULT hr = S_OK;
	SYNC_OBJ(&m_lockSection)

		//m_mapCls.end() == cls no_found == > false
		//m_mapCls.end() != cls  found == > true
		//rc_assert(!false)

	ClsIdTableConstiterator cls = m_mapCls.find(clsid);
	rc_assert(m_mapCls.end() != cls, E_INVALIDARG);

	ContainerTableConstiterator it = m_mapContainer.find(cls->second.pname);
	rc_assert((m_mapContainer.end() != it), E_INVALIDARG);

	ComFactoryPtr pfac;

	hr = it->second.DllGetClassObject(clsid,
		IID_IComObjectFrameworkClassFactory,
		(void**)&pfac);

	rc_assert(hr == S_OK, E_FAIL);
	rc_assert(pfac.m_p != NULL, E_FAIL);

	return pfac->CreateInstance(rot, punk, iid, ppv);
}

std_method_type_impl(LPCSTR) CObjectLoader::ProgIDFromCLSID(REFCLSID clsid)
{
	SYNC_OBJ(&m_lockSection)
	ClsIdTableConstiterator it = m_mapCls.find(clsid);
	rc_assert((m_mapCls.end() != it), "");
	return it->second.progid.c_str();
}

std_method_type_impl(CLSID) CObjectLoader::CLSIDFromProgID(LPCSTR lpProgId)
{
	rc_assert(lpProgId && *lpProgId, COMPONENT_NULL);
	SYNC_OBJ(&m_lockSection)

	size_t sSize = m_mapCls.size();
	rc_assert(sSize > 0, COMPONENT_NULL);

	ClsIdTableiterator it = m_mapCls.begin();
	for (; it != m_mapCls.end(); it++)
	{
		ClsInfo &cls = it->second;
		if (0 == string_stricmp(cls.progid.c_str(), lpProgId))
		{
			return it->first;
		}
	}
	return COMPONENT_NULL;
}

